/*
 * Utilities.java  0.4.0 / Oct 23, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

/**
 * Helper class.
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public final class Utilities {

// Private Constructor. --------------------------------------------------------

 /**
  * Class has no instances.
  */
  private Utilities() {
    // empty constructor body
  }

// Public Static Methods. ------------------------------------------------------

  /**
   * Returns <tt>true</tt> if the specified objects are <tt>equal</tt> or both
   *         are <tt>null</tt>.
   *
   * @param obj1 the first object
   * @param obj2 the second object
   *
   * @return <tt>true</tt> if the specified objects are <tt>equal</tt> or both
   *         are <tt>null</tt>
   */
  public static boolean equals(Object obj1, Object obj2) {
    return (obj1 == obj2) || ((obj1 != null) && (obj2 != null) &&  // NOPMD
                              obj1.equals(obj2));
  }

  /**
   * Extracts bytes from specified input stream.
   *
   * @param is the input stream
   *
   * @return extracted bytes from input stream
   *
   * @throws IOException on an I/O error
   */
  public static byte[] toByteArray(InputStream is) throws IOException {
    if (is == null) {
      throw new IllegalArgumentException("Null input stream");
    }
    try {
      int dataLen = is.available();
      if (dataLen == 0) {
        dataLen = 2 * 1024;
      }
      byte[] buffer = new byte[dataLen];
      int bytesRead = 0;
      int next;
      // TODO: reimplement
      while ((bytesRead += is.read(buffer, bytesRead, // NOPMD
                                   buffer.length - bytesRead)) != -1) {
        next = is.read();
        if (next < 0) {
          break;
        }
        if (bytesRead == buffer.length) {
          int newLength = ((3 * bytesRead) >> 1);
          byte[] newBuffer  = new byte[++newLength];
          System.arraycopy(buffer, 0, newBuffer, 0, bytesRead);
          buffer = newBuffer;
        }
        buffer[bytesRead++] = (byte)next;
      }
      if (bytesRead == dataLen) {
        return buffer;
      }
      byte[] data = new byte[bytesRead];
      System.arraycopy(buffer, 0, data, 0, bytesRead);
      return data;
    } finally {
      is.close();
    }
  }

  /**
   * Reads read content as string.
   *
   * @param reader the reader
   *
   * @return reader's content as string
   *
   * @throws IOException on an I/O error
   */
  public static String toString(Reader reader) throws IOException {
    if (reader == null) {
      throw new IOException("Null reader");
    }
    StringBuffer sb = new StringBuffer();
    try {
      int chunk = 16 * 1024;
      char[] buffer = new char[chunk];
      while ((chunk = reader.read(buffer, 0, chunk)) != -1) { // NOPMD
        sb.append(buffer, 0, chunk);
      }
      return sb.toString();
    } finally {
      reader.close();
    }
  }

  /**
   * Reads all input stream content as string.
   *
   * @param is the input stream
   *
   * @return input stream content as string
   *
   * @throws IOException on an I/O error
   */
  public static String toString(InputStream is) throws IOException {
    if (is == null) {
      throw new IOException("Null input stream");
    }
    return toString(new BufferedReader(new InputStreamReader(is)));
  }

}
